package com.jacobson.core.framework.errorhandler

import com.jacobson.core.widget.logger.LoggerFactory
import io.reactivex.Observer
import io.reactivex.disposables.Disposable

/**
 * ================================================
 *
 *  @author Wucz on 2018/7/24 11:18
 * ================================================
 */
abstract class RxHandlerSubscriber<T>(
        private val rxErrorHandler: RxErrorHandler
) : Observer<T> {
    private val logger = LoggerFactory.getLogger(pre = "RxHandlerSubscriber >>> ")

    override fun onComplete() {
        logger.e("onComplete")
    }

    override fun onSubscribe(d: Disposable) {
        logger.e("onSubscribe")
    }


    override fun onNext(t: T) {
        logger.e("onNext: $t")
        onSuccess(t)
    }

    override fun onError(e: Throwable) {
        logger.e("onError: ${e.localizedMessage}")
        e.printStackTrace()
        val code: Int
        val message: String?
        when (e) {
            is ResponseException -> {
                //如果是ResponseException类型
                code = e.code
                message = e.message
            }
            else -> {
                code = 0
                message = "未知错误"
            }
        }
        if (!onFailure(code, message)) {
            rxErrorHandler.handleError(e)
        }
    }

    protected open fun onFailure(code: Int, message: String?): Boolean = false
    protected open fun onError(code: Int, message: String?): Boolean = false
    abstract fun onSuccess(data: T)
    protected open fun filter(data: T): Nothing = throw IllegalArgumentException()

    class Builder<T>(val rxErrorHandler: RxErrorHandler) {
        var prevFilterListener: ((success: Boolean) -> Unit)? = null
        var postFilterListener: ((success: Boolean) -> Unit)? = null
        var failure: ((code: Int, message: String) -> Boolean)? = null
        lateinit var success: (data: T) -> Unit

        fun prevFilter(prevFilterListener: (success: Boolean) -> Unit): Builder<T> {
            this.prevFilterListener = prevFilterListener
            return this
        }

        fun success(success: (data: T) -> Unit): Builder<T> {
            this.success = success
            return this
        }

        fun failure(failure: (code: Int, message: String) -> Boolean): Builder<T> {
            this.failure = failure
            return this
        }

        fun postFilter(postFilterListener: (success: Boolean) -> Unit): Builder<T> {
            this.postFilterListener = postFilterListener
            return this
        }

        fun build(): RxHandlerSubscriber<T> {
            return object : RxHandlerSubscriber<T>(rxErrorHandler) {
                override fun onSuccess(data: T) {
                    prevFilterListener?.invoke(true)
                    success(data)
                    postFilterListener?.invoke(true)
                }

                override fun onFailure(code: Int, message: String?): Boolean {
                    prevFilterListener?.invoke(false)
                    return failure?.invoke(code, message ?: "")
                            .apply { postFilterListener?.invoke(false) }
                            ?: false
                }
            }
        }
    }

    companion object {
        fun <T> newRxResultHandler(builder: Builder<T>): RxHandlerSubscriber<T> = builder.build()

        fun <T> newRxResultHandler(
                rxErrorHandler: RxErrorHandler,
                success: (data: T) -> Unit,
                failure: ((code: Int, message: String?) -> Boolean) = { _: Int, _: String? -> false }
        ): RxHandlerSubscriber<T> {
            return object : RxHandlerSubscriber<T>(rxErrorHandler) {
                override fun onSuccess(data: T) {
                    success(data)
                }

                override fun onFailure(code: Int, message: String?): Boolean {
                    return failure(code, message)
                }
            }
        }

        fun <T> newRxResultHandler(
                rxErrorHandler: RxErrorHandler,
                success: (data: T) -> Unit
        ): RxHandlerSubscriber<T> {
            return object : RxHandlerSubscriber<T>(rxErrorHandler) {
                override fun onSuccess(data: T) {
                    success(data)
                }
            }
        }
    }
}